package com.example.e_comm.service.ServiceImpl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.e_comm.dto.UserDTO;
import com.example.e_comm.entity.User;
import com.example.e_comm.mapper.UserMapper;
import com.example.e_comm.service.UserService;
import com.example.e_comm.util.RedisUtil;
import com.example.e_comm.util.TokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private TokenUtil tokenUtil;

    @Override
    public boolean create(UserDTO dto) {
        User u = new User();
        u.setUsername(dto.getUsername());
        u.setEmail(dto.getEmail());
        u.setPassword(dto.getPassword());
        u.setAvatarUrl(dto.getAvatarUrl());
        return userMapper.insert(u) > 0;
    }

    @Override
    public boolean remove(Long id) {
        return userMapper.deleteById(id) > 0;
    }

    @Override
    public User get(Long id) {
        return userMapper.selectById(id);
    }

    @Override
    public IPage<User> pageUsers(Page<User> page) {
        return userMapper.selectPage(page, null);
    }

    @Override
    public IPage<User> pageUsersWithCondition(Page<User> page, String keyword) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(keyword)) {
            wrapper.like("username", keyword)
                   .or()
                   .like("email", keyword);
        }
        return userMapper.selectPage(page, wrapper);
    }

    @Override
    public List<User> list() {
        return userMapper.selectList(
                new LambdaQueryWrapper<User>().orderByAsc(User::getId));
    }

    @Override
    public boolean register(User user) {
        if (this.count(new QueryWrapper<User>().eq("username", user.getUsername())) > 0) {
            throw new IllegalArgumentException("用户名已存在,请替换其他用户名!");
        }
        if (this.count(new QueryWrapper<User>().eq("email", user.getEmail())) > 0) {
            throw new IllegalArgumentException("邮箱已被注册!");
        }
        if (user.getPassword() == null || user.getPassword().isEmpty()) {
            throw new IllegalArgumentException("密码不能为空!");
        }
        user.setPassword(DigestUtils.md5DigestAsHex(user.getPassword().getBytes()));
        user.setStatus(1);
        return this.save(user);
    }


    @Override
    public String login(String username, String password) {
        if (StringUtils.isEmpty(username) && StringUtils.isEmpty(password)){
            throw new  IllegalArgumentException("用户名或密码不能为空!");
        }
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();//用于实现查询条件对象
        //根据用户名和密码查询状态为在用的用户
        queryWrapper.eq("username", username)
                .eq("password", DigestUtils.md5DigestAsHex(password.getBytes()))
                .eq("status", 1);
        User user = this.getOne(queryWrapper);
        if (user == null) {
            throw new IllegalArgumentException("用户名或密码错误!");
        }
        //为找到用户生成token
        String token = tokenUtil.generaToken();
        //将token保存到redis中
        redisUtil.set("user:token:" + token, user.getId().toString(), 30, TimeUnit.MINUTES);
        redisUtil.set("user:id:" +user.getId(), token, 30, TimeUnit.MINUTES);
        return token;
    }

    @Override
    public User getUserByToken(String token) {
        //查找Redis缓存中是否有token
        if(!tokenUtil.validateToken(token)){
            return null;
        }
        Object userIdObj = redisUtil.get("user:token:" + token);
        if (userIdObj == null) {
            return null;
        }
        try{
            Long userId = Long.valueOf(userIdObj.toString());
            User user = this.getById(userId);
            if (user != null){
                redisUtil.set("user:token:" + token, user.getId().toString(), 30, TimeUnit.MINUTES);
                redisUtil.set("user:id:" +user.getId(), token, 30, TimeUnit.MINUTES);
            }
            return user;
        } catch (Exception e){
            System.err.println("没有找到与这个token适配的User：" + e.getMessage());
            return null;
        }
    }

    @Override
    public boolean logout(String token) {
        User user = getUserByToken(token);
        if (user != null) {
            redisUtil.delete("user:token:" + token);
            redisUtil.delete("user:id:" + user.getId());
            return true;
        }
        return false;
    }
    public boolean validateToken(String token){
        return redisUtil.hasKey("user:token:" + token);
    }
}